package services

import (
	"context"
	"fmt"
	"log"
	"sync"
	"time"

	"cdk.tf/go/stack/interfaces"
	"cdk.tf/go/stack/models"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/ec2"
	"github.com/aws/aws-sdk-go-v2/service/ec2/types"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
	"github.com/cdktf/cdktf-provider-aws-go/aws/v17/instance"
	"github.com/hashicorp/terraform-cdk-go/cdktf"
	// "your-project/interfaces"
	// "your-project/models"
)

type EC2Service struct {
	instances        map[string]*instance.Instance          // CDKTF 实例引用
	instanceMetadata map[string]*models.EC2InstanceMetadata // 实例元数据
	awsClientManager *AWSClientManager
	mu               sync.RWMutex
}

func NewEC2Service(awsClientManager *AWSClientManager) *EC2Service {
	return &EC2Service{
		instances:        make(map[string]*instance.Instance),
		instanceMetadata: make(map[string]*models.EC2InstanceMetadata),
		awsClientManager: awsClientManager,
	}
}

func (s *EC2Service) CreateEC2Instance(scope constructs.Construct, id string, config *interfaces.EC2Config) (*instance.Instance, error) {
	// 构建实例配置
	instanceConfig := &instance.InstanceConfig{
		Ami:                      jsii.String(config.AmiID),
		InstanceType:             jsii.String(config.InstanceType),
		KeyName:                  jsii.String(config.KeyName),
		Tags:                     convertTags(config.Tags),
		AssociatePublicIpAddress: jsii.Bool(config.AssociatePublicIP),
	}

	// 设置网络配置
	if config.SubnetID != "" {
		instanceConfig.SubnetId = jsii.String(config.SubnetID)
	}

	if len(config.SecurityGroupIDs) > 0 {
		instanceConfig.VpcSecurityGroupIds = &config.SecurityGroupIDs
	}

	// 设置用户数据
	if config.UserData != "" {
		instanceConfig.UserData = jsii.String(config.UserData)
	}

	// 创建 EC2 实例
	ec2Instance := instance.NewInstance(scope, jsii.String(id), instanceConfig)

	// 添加 Terraform 输出
	cdktf.NewTerraformOutput(scope, jsii.String(fmt.Sprintf("%s_id", id)), &cdktf.TerraformOutputConfig{
		Value:       ec2Instance.Id(),
		Description: jsii.String(fmt.Sprintf("ID of the %s instance", config.Name)),
	})

	cdktf.NewTerraformOutput(scope, jsii.String(fmt.Sprintf("%s_public_ip", id)), &cdktf.TerraformOutputConfig{
		Value:       ec2Instance.PublicIp(),
		Description: jsii.String(fmt.Sprintf("Public IP of the %s instance", config.Name)),
	})

	// 存储实例引用和元数据
	s.mu.Lock()
	resourceName := fmt.Sprintf("%s-%s", id, config.Name)
	s.instances[resourceName] = &ec2Instance
	s.instanceMetadata[resourceName] = &models.EC2InstanceMetadata{
		Config:       config,
		CreatedAt:    time.Now(),
		ResourceName: resourceName,
		Region:       "us-west-2", // 从配置中获取
	}
	s.mu.Unlock()

	log.Printf("EC2 instance %s created successfully", config.Name)
	return &ec2Instance, nil
}

func (s *EC2Service) WaitForInstanceRunning(instanceID, region string, timeout time.Duration) error {
	_, err := s.awsClientManager.GetEC2Client(region)
	if err != nil {
		return err
	}

	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	for {
		select {
		case <-ctx.Done():
			return fmt.Errorf("timeout waiting for instance %s to be running", instanceID)
		case <-time.After(10 * time.Second):
			instanceInfo, err := s.GetInstanceInfoAWS(instanceID, region)
			if err != nil {
				return err
			}

			if instanceInfo.State == "running" {
				return nil
			}

			log.Printf("Instance %s state: %s, waiting...", instanceID, instanceInfo.State)
		}
	}
}

func (s *EC2Service) GetInstanceInfoAWS(instanceID, region string) (*models.EC2InstanceResponse, error) {
	client, err := s.awsClientManager.GetEC2Client(region)
	if err != nil {
		return nil, err
	}

	input := &ec2.DescribeInstancesInput{
		InstanceIds: []string{instanceID},
	}

	result, err := client.DescribeInstances(context.TODO(), input)
	if err != nil {
		return nil, fmt.Errorf("failed to describe instance: %v", err)
	}

	if len(result.Reservations) == 0 || len(result.Reservations[0].Instances) == 0 {
		return nil, fmt.Errorf("instance not found: %s", instanceID)
	}

	awsInstance := result.Reservations[0].Instances[0]
	return s.convertAWSInstanceToResponse(awsInstance), nil
}

func (s *EC2Service) GetAllInstancesInfo(region string) ([]*models.EC2InstanceResponse, error) {
	client, err := s.awsClientManager.GetEC2Client(region)
	if err != nil {
		return nil, err
	}

	input := &ec2.DescribeInstancesInput{}
	result, err := client.DescribeInstances(context.TODO(), input)
	if err != nil {
		return nil, err
	}

	var instances []*models.EC2InstanceResponse
	for _, reservation := range result.Reservations {
		for _, awsInstance := range reservation.Instances {
			instances = append(instances, s.convertAWSInstanceToResponse(awsInstance))
		}
	}

	return instances, nil
}

func (s *EC2Service) GetInstancesBySubnet(subnetID, region string) ([]*models.EC2InstanceResponse, error) {
	client, err := s.awsClientManager.GetEC2Client(region)
	if err != nil {
		return nil, err
	}

	input := &ec2.DescribeInstancesInput{
		Filters: []types.Filter{
			{
				Name:   aws.String("subnet-id"),
				Values: []string{subnetID},
			},
		},
	}

	result, err := client.DescribeInstances(context.TODO(), input)
	if err != nil {
		return nil, err
	}

	var instances []*models.EC2InstanceResponse
	for _, reservation := range result.Reservations {
		for _, awsInstance := range reservation.Instances {
			instances = append(instances, s.convertAWSInstanceToResponse(awsInstance))
		}
	}

	return instances, nil
}

func (s *EC2Service) GetInstancesBySecurityGroup(sgID, region string) ([]*models.EC2InstanceResponse, error) {
	client, err := s.awsClientManager.GetEC2Client(region)
	if err != nil {
		return nil, err
	}

	input := &ec2.DescribeInstancesInput{
		Filters: []types.Filter{
			{
				Name:   aws.String("instance.group-id"),
				Values: []string{sgID},
			},
		},
	}

	result, err := client.DescribeInstances(context.TODO(), input)
	if err != nil {
		return nil, err
	}

	var instances []*models.EC2InstanceResponse
	for _, reservation := range result.Reservations {
		for _, awsInstance := range reservation.Instances {
			instances = append(instances, s.convertAWSInstanceToResponse(awsInstance))
		}
	}

	return instances, nil
}

func (s *EC2Service) TerminateInstance(instanceID, region string) error {
	client, err := s.awsClientManager.GetEC2Client(region)
	if err != nil {
		return err
	}

	input := &ec2.TerminateInstancesInput{
		InstanceIds: []string{instanceID},
	}

	_, err = client.TerminateInstances(context.TODO(), input)
	if err != nil {
		return err
	}

	log.Printf("Instance %s termination initiated", instanceID)
	return nil
}

func (s *EC2Service) convertAWSInstanceToResponse(awsInstance types.Instance) *models.EC2InstanceResponse {
	response := &models.EC2InstanceResponse{
		InstanceID:   aws.ToString(awsInstance.InstanceId),
		State:        string(awsInstance.State.Name),
		InstanceType: string(awsInstance.InstanceType),
		LaunchTime:   aws.ToTime(awsInstance.LaunchTime),
	}

	if awsInstance.PublicIpAddress != nil {
		response.PublicIP = *awsInstance.PublicIpAddress
	}

	if awsInstance.PrivateIpAddress != nil {
		response.PrivateIP = *awsInstance.PrivateIpAddress
	}

	if awsInstance.SubnetId != nil {
		response.SubnetID = *awsInstance.SubnetId
	}

	if awsInstance.VpcId != nil {
		response.VPCID = *awsInstance.VpcId
	}

	// 提取标签
	if awsInstance.Tags != nil {
		tags := make(map[string]string)
		for _, tag := range awsInstance.Tags {
			if tag.Key != nil && tag.Value != nil {
				tags[*tag.Key] = *tag.Value
			}
		}
		response.Tags = tags
	}

	// 提取安全组
	if awsInstance.SecurityGroups != nil {
		securityGroups := make([]string, len(awsInstance.SecurityGroups))
		for i, sg := range awsInstance.SecurityGroups {
			if sg.GroupId != nil {
				securityGroups[i] = *sg.GroupId
			}
		}
		response.SecurityGroups = securityGroups
	}

	return response
}

// 辅助函数
func convertTags(tags map[string]string) *map[string]*string {
	result := make(map[string]*string)
	for k, v := range tags {
		result[k] = jsii.String(v)
	}
	return &result
}
